/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "资源异步加载.h"
#include "纹理/纹理.h"

#include "MBT_Engine.h"


#include <stack>
#include <queue>

static bool        g有运行线程 = false;
//static int32       g加载数量 = 0;
static int32       g延迟 = 0;
static std::thread gThreads;
//static std::vector<S_纹理添加列队*> g待加载纹理列队;

CORE_ARRAY_HANDLE(S_待加载纹理列队, S_纹理添加列队*)

static S_待加载纹理列队& g待加载纹理列队 = *(S_待加载纹理列队*)f_core_array_new(0, sizeof(S_纹理添加列队*));

//static std::queue<S_纹理添加列队> g待加载纹理列队;

static std::mutex g_资源列队分配内存锁;


static void f_资源异步加载线程() {
	++S_Engine::g_在运行线程;

	while (S_Engine::m_资源加载线程) {
		
		if (g_资源列队分配内存锁.try_lock()) {
			uint32 num = g待加载纹理列队.count;
			for (uint32 i = 0; i < num; ++i) {
				if (g待加载纹理列队.ptr_userData[i]->m_内存数据 == nullptr) {
					f_tex_加载图像文件(*g待加载纹理列队.ptr_userData[i]);
					break;
				}
				//g待加载纹理列队[i].m_Scene->m_光追后端->m_待加载纹理列队.push_back(g待加载纹理列队[i]);
			}
			


			if (num) {
				S_光追后端::g_资源分配内存锁.lock();

				if (g待加载纹理列队.ptr_userData[0]->m_内存数据) {
					g待加载纹理列队.ptr_userData[0]->m_Scene->m_光追后端->m_待加载纹理列队.push_back(*g待加载纹理列队.ptr_userData[0]);
					delete g待加载纹理列队.ptr_userData[0];
					f_core_array_erase((S_Array*)&g待加载纹理列队, 0);
					//g待加载纹理列队.erase(g待加载纹理列队.begin());
				}

				S_光追后端::g_资源分配内存锁.unlock();
			}

			g_资源列队分配内存锁.unlock();
		}
		else {
			std::this_thread::sleep_for(std::chrono::milliseconds(g延迟));
			if (g延迟 < 2000) g延迟 += 20;
		}
	}

	--S_Engine::g_在运行线程;
}



void f_scene_往渲染器里添加纹理(const S_纹理添加列队& 纹理加载信息) {
	g_资源列队分配内存锁.lock();

	S_纹理添加列队* 列队数据指针 = new S_纹理添加列队;
	列队数据指针->m_Scene = 纹理加载信息.m_Scene;
	列队数据指针->m_加载路径 = 纹理加载信息.m_加载路径;
	列队数据指针->m_纹理对象 = 纹理加载信息.m_纹理对象;
	列队数据指针->m_新大小 = {};
	列队数据指针->m_内存数据 = nullptr;

	//纹理加载信息.m_Scene->m_光追后端->m_待加载纹理列队.push_back(纹理加载信息);
	f_core_array_push_back((S_Array*)&g待加载纹理列队, (uint8*)&列队数据指针);
	//g待加载纹理列队.push_back(列队数据指针);
	g延迟 = 0;

	g_资源列队分配内存锁.unlock();

	if (!g有运行线程) {
		gThreads = std::thread(f_资源异步加载线程);
		g有运行线程 = true;
	}
}

void f_scene_从渲染器里移除纹理(const S_纹理添加列队& 纹理移除信息) {
	S_光追后端::g_资源分配内存锁.lock();



	S_光追后端::g_资源分配内存锁.unlock();
}

S_纹理* f_scene_创建纹理(S_Scene* scene, S_设备环境& ctx, std::wstring name, S_光追后端::E_纹理分组类型 分组, S_纹理* Tex) {
	static S_纹理采样器* 默认采样器 = f_tex_创建纹理采样器(ctx);

	if (!Tex) {
		Tex = f_tex_创建图像纹理(ctx, { 64,64,1 }, E_纹理格式::e_tf_RGBA8U_U, E_纹理维度类型::e_2D);
		f_tex_安装纹理采样器(Tex, 默认采样器);
	}
	else {
		f_tex_安装纹理采样器(Tex, 默认采样器);
	}
	
	std::vector<S_MapPtrItem>* 纹理库 = nullptr;
	switch (分组) {
		case S_光追后端::e_2D纹理:
			纹理库 = &S_光追后端::G纹理;
			break;
		case S_光追后端::e_字符纹理:
			纹理库 = &S_光追后端::G字符纹理;
			break;
	}

	scene->m_光追后端->g_资源分配内存锁.lock();

	Tex->m_TexID = 纹理库->size();

	static C_StrKey分配器 g_纹理对象名称分配器;

	uint32 num = 纹理库->size();
	auto* data = 纹理库->data();

	bool 扩充容器 = true;
	for (uint32 i = 0; i < num; ++i) {
		if (data[i].m_Ptr == nullptr) {
			扩充容器 = false;

			data[i].m_Ptr = Tex;
			scene->m_光追后端->f_set纹理(Tex);
			break;
		}
	}
	if (扩充容器) {
		S_MapPtrItem item;
		item.m_Ptr = Tex;
		item.m_Str = g_纹理对象名称分配器.f_Gen(name);
		纹理库->push_back(item);

		scene->m_光追后端->f_add纹理(Tex, Tex->m_TexID, 分组);
	}

	scene->m_光追后端->g_资源分配内存锁.unlock();
	return Tex;
}

bool f_scene_销毁纹理(S_Scene* scene, S_纹理* tex, S_光追后端::E_纹理分组类型 分组) {
	std::vector<S_MapPtrItem>* 纹理库 = nullptr;
	switch (分组) {
		case S_光追后端::e_2D纹理:
			纹理库 = &S_光追后端::G纹理;
			break;
		case S_光追后端::e_字符纹理:
			纹理库 = &S_光追后端::G字符纹理;
			break;
	}


	scene->m_光追后端->g_资源分配内存锁.lock();

	uint32 num = 纹理库->size();
	auto* data = 纹理库->data();
	for (uint32 i = 0; i < num; ++i) {
		if (data[i].m_Ptr == tex) {
			S_纹理* t = (S_纹理*)data[i].m_Ptr;
			//f_NodeCtx_get默认场景()->m_光追后端->f_rem纹理(i);
			f_tex_销毁纹理(t);

			data[i].m_Ptr = nullptr;
			纹理库->erase(纹理库->begin() + i);
			break;
		}
	}

	scene->m_光追后端->g_资源分配内存锁.unlock();
	return false;
}

bool f_scene_销毁渲染器纹理(S_Scene* scene, uint32 保留数量, S_光追后端::E_纹理分组类型 分组) {
	scene->m_光追后端->g_资源分配内存锁.lock();

	switch (分组) {
		case S_光追后端::e_2D纹理:{
			uint32 num = S_光追后端::G纹理.size();
			auto* data = S_光追后端::G纹理.data();
			for (uint32 i = 保留数量; i < num; ++i) {
				if (data[i].m_Ptr) {
					S_纹理* t = (S_纹理*)data[i].m_Ptr;
				}
			}
			S_光追后端::G纹理.resize(保留数量);
			break;
		}
		case S_光追后端::e_字符纹理:{
			uint32 num = S_光追后端::G字符纹理.size();
			auto* data = S_光追后端::G字符纹理.data();
			for (uint32 i = 保留数量; i < num; ++i) {
				if (data[i].m_Ptr) {
					S_纹理* t = (S_纹理*)data[i].m_Ptr;
				}
			}
			S_光追后端::G字符纹理.resize(保留数量);
			break;
		}
	}

	scene->m_光追后端->g_资源分配内存锁.unlock();
	return false;
}






